package com.poplar.fancyprogress; import static com.poplar.fancyprogress.utils.Utils.evalute; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PointF; import android.support.v4.view.MotionEventCompat; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.animation.LinearInterpolator; import com.nineoldandroids.animation.ValueAnimator; import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener; public class FancyProgress4 extends View { private int[] COLORS = new int[] { Color.parseColor("#FC5652"), Color.parseColor("#1E4B58"), Color.parseColor("#FEB364"), Color.parseColor("#00B29E"), }; private float mRadius = 16f; private float mDistance2Next = 50.0f; private int mOneShotDuration = 1000; private float mStayPercent = 0.1f; private PointF[] mBallCenters = new PointF[]{ new PointF(0, 0), new PointF(0 + mDistance2Next, 0), new PointF(0 + mDistance2Next, 0 + mDistance2Next), new PointF(0, 0 + mDistance2Next), }; private float mPercent = 0; private Paint mPaint; private ValueAnimator mAnim; public FancyProgress4(Context context) { this(context, null); } public FancyProgress4(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FancyProgress4(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); } public void show(){ mAnim = ValueAnimator.ofFloat(1.0f); mAnim.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mPercent = animation.getAnimatedFraction(); invalidate(); } }); mAnim.setInterpolator(new LinearInterpolator()); mAnim.setRepeatCount(ValueAnimator.INFINITE); mAnim.setDuration(mOneShotDuration * 4); mAnim.start(); } private float mStartX; @Override public boolean onTouchEvent(MotionEvent event) { switch (MotionEventCompat.getActionMasked(event)) { case MotionEvent.ACTION_DOWN: mStartX = event.getRawX(); break; case MotionEvent.ACTION_MOVE: float distance = event.getRawX() - mStartX; long playTime = (long) ((distance * 20) % (mOneShotDuration * 4)); mAnim.setCurrentPlayTime(playTime); break; case MotionEvent.ACTION_UP: break; default: break; } return true; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int measuredWidth = MeasureSpec.makeMeasureSpec((int)(mRadius * 2 + mDistance2Next), MeasureSpec.EXACTLY); int measuredHeight = MeasureSpec.makeMeasureSpec((int)(mRadius * 2 + mDistance2Next), MeasureSpec.EXACTLY); setMeasuredDimension(measuredWidth, measuredHeight); } @Override protected void onDraw(Canvas canvas) { canvas.save(); canvas.translate(mRadius, mRadius); for (int i = 0; i < mBallCenters.length; i++) { mPaint.setColor(COLORS[i]); PointF mCurrentCenter = getCurrentCenter(i, mPercent); canvas.drawCircle(mCurrentCenter.x, mCurrentCenter.y, mRadius, mPaint); } canvas.restore(); } /** * 获取当前坐标中心 * @param pointF * @param i * @param percent * @return */ private PointF getCurrentCenter(int i, float percent) { PointF startP = null; PointF endP = null; float fraction = 0; int startOffset = (int) (percent / 0.25f); int endOffset = startOffset + 1; startP = getPointFromOffset(startOffset, i); endP = getPointFromOffset(endOffset, i); fraction = percent % 0.25f / 0.25f; Log.d("TAG", "center percent: " + (float)(Math.round(percent*100))/100); if(fraction < mStayPercent){ return startP; }else if (fraction > 1 - mStayPercent) { return endP; }else { fraction = (fraction - mStayPercent) / (1.0f - mStayPercent * 2f); return new PointF(evalute(fraction, startP.x, endP.x), evalute(fraction, startP.y, endP.y)); } } private PointF getPointFromOffset(int startOffset, int i) { return mBallCenters[Math.abs(i + startOffset) % mBallCenters.length]; } public void dismiss(){ setVisibility(View.INVISIBLE); if(mAnim != null){ mAnim.end(); } } }